#ifndef COMMONS_H
#define COMMONS_H
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef unsigned char   u8;
typedef signed char     s8;
typedef unsigned short  u16;
typedef signed short    s16;
typedef unsigned int    u32;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef u8 (*Z80ReadMemory)( u16 );
typedef void ( *Z80WriteMemory )( u16, u8 );
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ROM_SIZE    0x10000
#define BANK_SIZE   0x8000 // arranco con los roms de un solo banco
#define PORTS_SIZE  0x100
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PORT_LCDC   0xFF40
#define PORT_STAT   0xFF41
#define PORT_LY     0xFF44
#define PORT_LYC    0xFF45
#define PORT_IF     0xFF0F
#define PORT_IE     0xFFFF
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define INTERRUPT_VBLANK    0
#define INTERRUPT_LCDC      1
#define INTERRUPT_TIMER     2
#define INTERRUPT_SERIAL    3
#define INTERRUPT_P10P13    4
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define SCANLINE_CYCLES 456
#define MODE_0_CYCLES   204
#define MODE_2_CYCLES   80
#define MODE_3_CYCLES   172
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define MAX_ACTIVE_SCANLINE 144
#define MAX_VBLANK_SCANLINE 153
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define FLAG_Z  0x80
#define FLAG_N  0x40
#define FLAG_H  0x20
#define FLAG_C  0x10
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef union {
    u16 W;
    struct {
        u8 L;
        u8 H;
    };
} PairRegister;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const int OpcodeCycles[256] = {
/*     0   1  2   3   4   5   6  7   8  9   A  B   C   D  E  F */
/*0*/  4, 12, 8,  8,  4,  4,  8, 8,  0, 0,  0, 8,  4,  4, 8, 8,
/*1*/  4, 12, 8,  8,  4,  0,  8, 8,  8, 0,  0, 8,  4,  4, 8, 8,
/*2*/  8, 12, 0,  8,  4,  0,  8, 4,  8, 0,  8, 8,  4,  4, 8, 4,
/*3*/  8, 12, 8,  8,  0,  0, 12, 4,  8, 0,  8, 8,  4,  4, 8, 4,
/*4*/  4,  4, 4,  4,  4,  4,  8, 4,  4, 4,  4, 4,  4,  4, 8, 4,
/*5*/  4,  4, 4,  4,  4,  4,  8, 4,  4, 4,  4, 4,  4,  4, 8, 4,
/*6*/  4,  4, 4,  4,  4,  4,  8, 4,  4, 4,  4, 4,  4,  4, 8, 4,
/*7*/  8,  8, 8,  8,  8,  8,  4, 8,  4, 4,  4, 4,  4,  4, 8, 4,
/*8*/  4,  4, 4,  4,  4,  4,  8, 4,  4, 4,  4, 4,  4,  4, 8, 4,
/*9*/  0,  0, 0,  0,  0,  0,  0, 0,  4, 4,  4, 4,  4,  4, 8, 4,
/*A*/  4,  4, 4,  4,  4,  4,  8, 4,  4, 4,  4, 4,  4,  4, 8, 4,
/*B*/  4,  4, 4,  4,  4,  4,  8, 4,  0, 0,  0, 0,  0,  0, 0, 0,
/*C*/  8,  0, 0, 12, 12, 16,  8, 0,  8, 8,  0, 0, 12, 12, 8, 0,
/*D*/  8,  0, 0,  0, 12, 16,  0, 0,  8, 0,  0, 0, 12,  0, 8, 0,
/*E*/ 12,  0, 8,  0,  0, 16,  8, 0,  0, 4, 16, 0,  0,  0, 8, 0,
/*F*/ 12,  0, 0,  4,  0, 16,  8, 0, 12, 0,  0, 4,  0,  0, 8, 0,
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const int ExtendedOpcodeCycles[256] = {
/*     0   1  2   3   4   5   6  7   8  9   A  B   C   D  E  F */
/*0*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*1*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*2*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*3*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*4*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*5*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*6*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*7*/  0,  0, 0,  0,  0,  0,  0, 0,  8, 0,  0, 0,  0,  0, 0, 0,
/*8*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*9*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*A*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*B*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*C*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*D*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*E*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
/*F*/  0,  0, 0,  0,  0,  0,  0, 0,  0, 0,  0, 0,  0,  0, 0, 0,
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
bool TestBit( T Reg, int Bit ) {
    T mask = (1 << Bit);
    
    return ( (Reg & mask) == mask );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
bool TestFlag( T FlagSet, u8 Flag ) {
    return ( (FlagSet & Flag) == Flag );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
